﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-12-30
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


#pragma pack(push, 1)


//----------------------------------------------------------------
// 用于数据转换的向量
//----------------------------------------------------------------
// POINT
FINLINE POINT FDT_POINT_CREATE(LONG x, LONG y)
{
    POINT pt = {x, y};
    return pt;
}
FINLINE bool operator == (const POINT& l, const POINT& r)
{
    return l.x == r.x && l.y == r.y;
}

// RECT
FINLINE RECT FDT_RECT_CREATE(LONG l, LONG t, LONG r, LONG b)
{
    RECT rc = {l, t, r, b};
    return rc;
}
FINLINE bool operator == (const RECT& l, const RECT& r)
{
    return l.left == r.left && l.right == r.right && l.top == r.top && l.bottom == r.bottom;
}

// VECTOR2
struct FDT_VECTOR2
{
    FDECLARE_STRUCT(FDT_VECTOR2)

    float x, y;
};
FINLINE FDT_VECTOR2 FDT_VECTOR2_CREATE(float _x, float _y)
{
    FDT_VECTOR2 v2 = {_x, _y};
    return v2;
}
FINLINE bool operator == (const FDT_VECTOR2& l, const FDT_VECTOR2& r)
{
    return l.x == r.x && l.y == r.y;
}

// VECTOR3
struct FDT_VECTOR3
{
    FDECLARE_STRUCT(FDT_VECTOR3)

    float x, y, z;
};
FINLINE FDT_VECTOR3 FDT_VECTO3_CREATE(float _x, float _y, float _z)
{
    FDT_VECTOR3 v3 = {_x, _y, _z};
    return v3;
}
FINLINE bool operator == (const FDT_VECTOR3& l, const FDT_VECTOR3& r)
{
    return l.x == r.x && l.y == r.y && l.z == r.z;
}

// VECTOR4
struct FDT_VECTOR4
{
    FDECLARE_STRUCT(FDT_VECTOR4)

    float x, y, z, w;
};
FINLINE FDT_VECTOR4 FDT_VECTOR4_CREATE(float _x, float _y, float _z, float _w)
{
    FDT_VECTOR4 v4 = {_x, _y, _z, _w};
    return v4;
}
FINLINE bool operator == (const FDT_VECTOR4& l, const FDT_VECTOR4& r)
{
    return l.x == r.x && l.y == r.y && l.z == r.z && l.w == r.w;
}


//----------------------------------------------------------------
// 数据类型
//----------------------------------------------------------------
enum EF_FDT_TYPE
{
    eFDT_unknown,       // void
    eFDT_bool,          // bool
    eFDT_char,          // char
    eFDT_uchar,         // unsigned char, BYTE
    eFDT_short,         // short
    eFDT_ushort,        // unsigned short, WORD
    eFDT_int,           // int
    eFDT_uint,          // unsigned int
    eFDT_long,          // long
    eFDT_ulong,         // unsigned long, DWORD
    eFDT_int64,         // INT64
    eFDT_uint64,        // UINT64
    eFDT_float,         // float
    eFDT_double,        // double
    eFDT_wchar_t,       // wchar_t
    eFDT_void_ptr,      // void*
    eFDT_point,         // POINT
    eFDT_rect,          // RECT
    eFDT_vec2,          // FDT_VECTOR2, float[2]
    eFDT_vec3,          // FDT_VECTOR3, float[3]
    eFDT_vec4,          // FDT_VECTOR4, float[4]

    eFDT_pwchar,        // const WCHAR* 手动指定此类型
    eFDT_pachar,        // const ACHAR* 手动指定此类型
};


//----------------------------------------------------------------
// 数据对象与值
//----------------------------------------------------------------
struct FDT_VALUE
{
    FDECLARE_STRUCT(FDT_VALUE)

    EF_FDT_TYPE t;
    union VALUE_TYPE
    {
        bool                b;
        char                c;
        unsigned char       uc;
        short               s;
        unsigned short      us;
        int                 i;
        unsigned int        ui;
        long                l;
        unsigned long       ul;
        INT64               i64;
        UINT64              ui64;
        float               f;
        double              d;
        wchar_t             wc;
        void*               pp;
        POINT               point;
        RECT                rect;
        FDT_VECTOR2         v2;
        FDT_VECTOR3         v3;
        FDT_VECTOR4         v4;
        const WCHAR*        pwcs;
        const ACHAR*        pacs;
    } v;

    FINLINE FDT_VALUE(EF_FDT_TYPE p = eFDT_unknown)
        :t(p)
    {
        FMemzero(&v, sizeof(v));
    }

    // 类开转换函数，安全处理
#define FDT_VALUE_FUNC(type, name, var)\
    FINLINE FDT_VALUE(const type& p){ v.var = p; t = eFDT_##name; }\
    FINLINE void operator = (const type& p){ t = eFDT_##name; v.var = p; }\
    FINLINE operator type(){ FASSERT(t == eFDT_##name, _T("期望的数据类型与实际类型不匹配")); return v.var; }\
    FINLINE bool operator == (const type& r) { return r == v.var; }

    FDT_VALUE_FUNC(bool, bool, b);
    FDT_VALUE_FUNC(char, char, c);
    FDT_VALUE_FUNC(unsigned char, uchar, uc);
    FDT_VALUE_FUNC(short, short, s);
    FDT_VALUE_FUNC(unsigned short, ushort, us);
    FDT_VALUE_FUNC(int, int, i);
    FDT_VALUE_FUNC(unsigned int, uint, ui);
    FDT_VALUE_FUNC(long, long, l);
    FDT_VALUE_FUNC(unsigned long, ulong, ul);
    FDT_VALUE_FUNC(INT64, int64, i64);
    FDT_VALUE_FUNC(UINT64, uint64, ui64);
    FDT_VALUE_FUNC(float, float, f);
    FDT_VALUE_FUNC(double, double, d);
    FDT_VALUE_FUNC(POINT, point, point);
    FDT_VALUE_FUNC(RECT, rect, rect);
    FDT_VALUE_FUNC(FDT_VECTOR2, vec2, v2);
    FDT_VALUE_FUNC(FDT_VECTOR3, vec3, v3);
    FDT_VALUE_FUNC(FDT_VECTOR4, vec4, v4);

    FINLINE FDT_VALUE(void* p){ v.pp = p; t = eFDT_void_ptr; }
    FINLINE void operator = (void* p){ FASSERT(t == eFDT_void_ptr, _T("期望的数据类型与实际类型不匹配")); v.pp = p; }
    FINLINE operator void*(){ FASSERT(t == eFDT_void_ptr, _T("期望的数据类型与实际类型不匹配")); return v.pp; }
};


#pragma pack(pop)


typedef FVector< FDT_VALUE > FV_DT_VALUE;


// 转换类型为字符串
extern FAPI const WCHAR* FGetDTNameW(EF_FDT_TYPE t);
extern FAPI const ACHAR* FGetDTNameA(EF_FDT_TYPE t);
extern FAPI const WCHAR* FGetDTValueW(FDT_VALUE v);
extern FAPI const ACHAR* FGetDTValueA(FDT_VALUE v);


#ifdef UNICODE
#define FGetDTName                  FGetDTNameW
#define FGetDTValue                 FGetDTValueW
#else
#define FGetDTName                  FGetDTNameA
#define FGetDTValue                 FGetDTValueA
#endif

#if FUEL_OS_WINDOWS
#define FFGetDTName                 FGetDTNameW
#define FFGetDTValue                FGetDTValueW
#else
#define FFGetDTName                 FGetDTNameA
#define FFGetDTValue                FGetDTValueA
#endif